Retrofit2 使用
第一步:定义接口服务类,该类只能是接口类型,里面通过 Retrofit
提供的注解类来定义一些请求方法,比如:
public interface BlogService {
@GET("blog/{id}")
Call<ResponseBody> getBlog(@Path("id") int id);
}
该接口定义了一个 GET
请求方法,方法名称为 getBlog
,返回的类型为 Call<ResponseBody>
。
第二步:创建接口实现类。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:4567/")
.build();
BlogService blogService = retrofit.create(BlogService.class);
首先创建 Retrofit
实例,必须要传入 baseUrl
,不然会报错。 该实例是通过 Builder
模式生成的,里面可以配置相当多的参数,然后通过 create
方法来生成实现类,底层通过动态代理的方式来实现。
第三步:调用相应接口方法,拿到 Call
实例,Call
对象是用来发起同步或异步请求的。
Call<ResponseBody> call = blogService.getBlog(2);
第四步:执行请求。
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
System.out.println("success: " + Thread.currentThread().getName());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
System.out.println("fail: " + Thread.currentThread().getName());
}
});
Retrofit 初始化
Retrofit
的构造函数只是单纯地进行赋值处理,我们看一下它的实例变量:
// 一个线程安全的、支持高效并发的HashMap,Key 是 Method,Value 是 ServiceMethod,主要是用来做缓存的,避免重复解析接口方法。
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
// Call 的工厂类,如果不自定义赋值,默认会是 OkHttpClient(实现了 Factory 接口)
final okhttp3.Call.Factory callFactory;
// HttpUrl 类型的地址
final HttpUrl baseUrl;
// 数据转换器
final List<Converter.Factory> converterFactories;
// Call 适配器
final List<CallAdapter.Factory> callAdapterFactories;
// 回调执行器,用来做线程切换的
final @Nullable Executor callbackExecutor;
// 是否提前检查接口注解信息
final boolean validateEagerly;
我们接着看 Builder
类:
public static final class Builder {
// 该类跟平台有关
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
}
总体跟 Retrofit
的变量差不多,只是多了一个 Platform
变量,该类跟运行的平台相关,源码如下:
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
get
方法会去调用 findPlatform
方法,这个里面很明显跟平台相关,Class.forName
要求 JVM
根据 className
查找并加载指定的类,如果未找到则抛出 ClassNotFoundException
。我们分析 Android
平台,所以会返回一个 Android
对象。
static class Android extends Platform {
// 获取默认的线程执行器
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
// 获取默认的 Call 适配器工厂类
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
// 创建 DefaultCallAdapterFactory
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
// 获取默认的数据转换器工厂类
@Override List<? extends Converter.Factory> defaultConverterFactories() {
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}
// 主线程执行器
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
该类主要是用于提供框架内部用到的 CallAdapter 工厂类、 Converter 工厂类和线程执行类,这几个类都非常重要,后面再分析。最后我们看一下 build
方法。
public Retrofit build() {
// baseUrl 是必不可少的
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// 如果没有传入该对象,则默认创建一个 OkHttpClient
callFactory = new OkHttpClient();
}
// 如果没有传入自定义的线程执行器
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 则拿到默认的执行器,Android 平台上为 MainThreadExecutor
callbackExecutor = platform.defaultCallbackExecutor();
}
// 先添加自定义的 CallAdapter ,最后添加框架默认的 CallAdapter,即 DefaultCallAdapterFactory
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 先添加框架的 BuiltInConverters ,然后添加自定义的 converter ,最后添加框架默认的 converter
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
// 返回 Retrofit 对象
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
到此,Retrofit
初始化就分析完成了 ,Retrofit
之前定义的变量大部分都涉及到了,具体这些变量怎么使用,我们接着分析。
创建接口实例
创建接口实例是通过 Retrofit
的 create
方法来实现的,我们看一下这个方法:
public <T> T create(final Class<T> service) {
// 提前检查接口方法
validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// 如果这个方法是声明在 Object 类中,那么不拦截,直接执行
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 这句代码非常关键
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
首先调用了 validateServiceInterface(service)
来提前检查接口方法,这个方法是由 validateEagerly
变量来控制的,源码如下:
if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
重点在于 loadServiceMethod
方法:
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
loadServiceMethod
里面会根据 Method
生成一个 ServiceMethod
,然后存入 serviceMethodCache
,这是属于提前验证,会提前把接口中每个方法进行解析得到一个 ServiceMethod
对象,然后放入缓存中。 在 loadServiceMethod
中会先取缓存中的值,如果存在就直接返回 ServiceMethod
。
回到 create
方法,接下来会调用 Proxy
的 newProxyInstance
方法来生成代理对象并强转为 T
类型,即对应的接口类型。由于拿到的是代理对象,所以在调用相应方法时,会先走 InvocationHandler
中的 invoke
方法,里面的重点方法就是 loadServiceMethod
,如果启动了提前检查功能,这里可以直接拿到 ServiceMethod
对象,然后接着调用 invoke
方法。不管有没有提前开启提前检查功能,都需要经过这个方法来获取相应的 ServiceMethod
对象,我们详解分析一下这个方法。
ServiceMethod<?> loadServiceMethod(Method method) {
// 首先从缓存 serviceMethodCache 中取 ServiceMethod ,如果存在就返回,不存在继续往下走。
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
//这里又从缓存取了一遍,看到这里有没有一种熟悉的感觉,是不是跟 DCL 单例模式特别像,双重校验。
result = serviceMethodCache.get(method);
if (result == null) {
// 获取 ServiceMethod 对象
result = ServiceMethod.parseAnnotations(this, method);
// 添加到缓存
serviceMethodCache.put(method, result);
}
}
return result;
}
上述方法返回的 ServiceMethod
对象最终是通过 ServiceMethod
的 parseAnnotations
方法返回的。ServiceMethod
是一个抽象类,它的子类为 HttpServiceMethod
,HttpServiceMethod
其实也是一个抽象类,我们先看一下 ServiceMethod
的源码:
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 获取 RequestFactory 类,该类包含所有的请求的基本参数
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 获取返回的类型,比如 Call<ResponseBody>
Type returnType = method.getGenericReturnType();
// 检查返回类型的有效性
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
// 返回一个 HttpServiceMethod 对象
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
该方法首先解析请求的基本参数,将解析后的所有请求参数封装到了 RequestFactory
对象,然后检查了方法的返回类型的有效性,最后通过 HttpServiceMethod
的 parseAnnotations
方法来获取 HttpServiceMethod
对象,我们首先分析一下 RequestFactory
类 ,该类里面有大量的解析注解的逻辑,最终会将解析的内容赋值到类变量里面,源码如下:
// 对应的接口方法
private final Method method;
// 请求地址
private final HttpUrl baseUrl;
// 请求方法(GET/POST等)
final String httpMethod;
// 请求相对地址,比如 “blog/{id}”
private final @Nullable String relativeUrl;
// 请求头
private final @Nullable Headers headers;
// 请求报文类型
private final @Nullable MediaType contentType;
// 是否有请求体
private final boolean hasBody;
// 是否使用表单提交方式
private final boolean isFormEncoded;
// 是否使用 Multipart 方式,用来文件上传
private final boolean isMultipart;
// 方法参数处理器,用来解析方法参数注解等
private final ParameterHandler<?>[] parameterHandlers;
以上为 RequestFactory
最重要的字段,由这些字段可知,该类主要是保存请求参数的,而这些参数是通过解析各种注解和方法得到的。我们接着看 HttpServiceMethod
的 parseAnnotations
方法:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
...
//比如 Call<ResponseBody>
adapterType = method.getGenericReturnType();
// 第一步,获取 CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// 比如 ResponseBody
Type responseType = callAdapter.responseType();
// 第二步,获取 Converter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 第三步,返回一个 CallAdapted 对象,该对象继承于 HttpServiceMethod
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
上述源码省略了一个参数的校验逻辑,主要关注整体流程,首先看第一步,最终会调用 retrofit
的 callAdapter
方法:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
// 注意第一个参数传入了 null
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
... 省略参数校验
//这里的 skipPast 是null, 所以 indexOf 肯定返回的 -1, 所以这里 start = 0
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
// adapter 不为null则返回,所以如果自定义的 Adapter 处理不了,返回 null 即可,交给下一个Adapter处理
if (adapter != null) {
return adapter;
}
}
}
上述代码中,参数 skipPast
为 null
,则 start
从 0
开始遍历,如果我们没有自定义 CallAdapter
,那么此时获取到的应该是框架内的 DefaultCallAdapterFactory
对象,接着会调用 get
方法来获取 CallAdapter
对象。
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 该默认的适配器只处理原始类型为 Call 类型的,刚好我们自定的适配类型为 Call<ResponseBody>,
// 所以这里拿到的源始类型为 Call 类型
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
// 获取返回类型,为 ResponseBody
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// 赋值回调执行器
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
// 构建一个 CallAdapter 返回
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
// 如果 executor 为null ,则直接返回 call ,否则返回 ExecutorCallbackCall (该类包装了 call ,里面有线程切换处理)
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
由源码可知,最后构建了一个 CallAdapter
返回,这个 CallAdapter
很重要,后面的请求流程需要用到。至此第一步分析完毕,接下来看第二步,获取 Converter
,流程跟获取 CallAdapter
类似 ,最后会调用 retrofit
的 responseBodyConverter
方法:
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
// 注意第一个参数传入了 null
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
... 省略参数校验
//这里的 skipPast 是null, 所以 indexOf 肯定返回的 -1, 所以这里 start = 0
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
// converter 不为null则返回,所以如果自定义的 converter 处理不了,返回 null 即可,交给下一个converter 处理
if (converter != null) {
return (Converter<ResponseBody, T>) converter;
}
}
}
在 retrofit
初始化的时候有讲到,第一个添加的 converter
为框架的 BuiltInConverters
,我们看一下它的 responseBodyConverter
方法:
@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
// 这里的类型为响应类型
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
if (checkForKotlinUnit) {
try {
if (type == Unit.class) {
return UnitResponseBodyConverter.INSTANCE;
}
} catch (NoClassDefFoundError ignored) {
checkForKotlinUnit = false;
}
}
return null;
}
这里先说明一下 Type
类型的种类,共有 3 种类型,一种是适配类型(比如 CallConverter
实例。最后我们看看第三步:
// 第三步,返回一个 CallAdapted 对象,该对象继承于 HttpServiceMethod
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
就是构建一个 CallAdapted
对象,并把所有的参数都传入该对象,我们看一下它的源码:
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
// 参数赋值
super(requestFactory, callFactory, responseConverter);
// 这是我们获取到的 callAdapter
this.callAdapter = callAdapter;
}
// 实现 HttpServiceMethod 的抽象方法
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
// 直接调用 callAdapter 的 adapt 方法,并把 call 传入
return callAdapter.adapt(call);
}
}
该类是 HttpServiceMethod
的内部类,HttpServiceMethod
是一个抽象类,有一个 adapt
的抽象方法。到此,我们分析了代理对象里面的 loadServiceMethod(method)
方法的逻辑,我们再看一下该方法:
// 这句代码非常关键
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
Call 对象获取流程分析
我们先看一下使用方法:
Call<ResponseBody> call = blogService.getBlog(2);
上述分析已经知道,最终会通过 CallAdapted
实例,并调用 invoke
方法来获取 Call
对象,用于接下来的同步或异步请求。那么我们就从 invoke
方法入手,该方法是在抽象类 ServiceMethod
中定义的抽象方法,具体由 HttpServiceMethod
类实现,那么我们直接看 HttpServiceMethod
的 invoke
方法:
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
该方法共有两步,第一步是构建 OkHttpCall
对象,第二步是调用 adapt
方法,并把 OkHttpCall
和请求参数传入。先分析第一步,直接看 OkHttpCall
的构建方法:
OkHttpCall(RequestFactory requestFactory, Object[] args,
okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;
this.args = args;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
非常简单,就是赋值操作,所以重点在于第二步的 CallAdapted
的 adapt
方法 :
// 实现 HttpServiceMethod 的抽象方法
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
// 直接调用 callAdapter 的 adapt 方法,并把 call 传入
return callAdapter.adapt(call);
}
直接调用 callAdapter
的 adapt
方法,并把 call
传入,之前我们分析到,该 callAdapter
就是在 DefaultCallAdapterFactory
的 get
方法中返回的,源码再看一下:
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 该默认的适配器只处理原始类型为 Call 类型的,刚好我们自定的适配类型为 Call<ResponseBody>,
// 所以这里拿到的源始类型为 Call 类型
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
// 获取返回类型,为 ResponseBody
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// 赋值回调执行器
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
// 构建一个 CallAdapter 返回
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
// 如果 executor 为null ,则直接返回 call ,否则返回 ExecutorCallbackCall (该类包装了 call ,里面有线程切换处理)
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
由于我们是在 Android
平台上运行上,所以 executor
不为 null
,为 MainThreadExecutor
,上述分析 Platform
类时在讲到,所以这里返回了 ExecutorCallbackCall
对象,该对象是 DefaultCallAdapterFactory
的内部类。
发起请求和获取响应流程分析
我们接着上面的流程,看一下 ExecutorCallbackCall 的源码:
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
// 赋值
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
// 执行异步请求
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
// 通过线程执行器执行任务
callbackExecutor.execute(() -> {
if (delegate.isCanceled()) {
// 失败回调
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
// 成功回调
callback.onResponse(ExecutorCallbackCall.this, response);
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
// 通过线程执行器执行任务,失败回调
callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
@Override public boolean isExecuted() {
return delegate.isExecuted();
}
@Override public Response<T> execute() throws IOException {
// 执行同步请求
return delegate.execute();
}
@Override public void cancel() {
// 取消请求
delegate.cancel();
}
@Override public boolean isCanceled() {
// 取消是否被取消
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
// 深度克隆,返回一个 Call 对象
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
// 获取 Request
return delegate.request();
}
}
该方法会通过 OkHttpCall
方法来执行相应的同步或异步请求,而在 OkHttpCall
里层会生成真正的请求类来执行请求处理在成功或失败之后,通过线程执行器来切换到主线程来进行用户的回调处理,所以我们在使用时的异步回调是在主线程的,可以直接进行 UI 处理,我们先看一下真正的 call
的生成过程 :
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
这段代码非常熟悉,就是通过 OkHttp
的方式,先构建 Request
对象,然后通过 OkHttpClient
对象的 newCall
方法生成真正的请求类来执行请求,我们看看异步请求的代码:
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 解析成想要的格式
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
// 回调成功
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
// 回调失败
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
OkHttpCall
对象里层真正发起请求的是 okhttp3.Call
对象,拿到响应结果后,先通过 parseResponse
方法进行数据格式转换,这里就需要用到 converter
了:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
// 获取源始的 ResponseBody 对象
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
// 根据响应码做相应处理
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
// 包装一个可以捕捉异常的对象
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 进行数据转换,默认转换的就是 ResponseBody,即不转换
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
该方法如其名,就是解析响应的,根据响应码做了相应的逻辑处理,然后通过转换器来转换成我们想要的数据类型并返回。到此,我们对每一步的流程都分析了。下面是整体流程图: